import logging
import math
import threading
import time

from ship import ship_factory, ship, ship_adj_table
from config import parse
from tool import mns_time
from log import mns_log

mns_log.Log.mns_logging()


class World(threading.Thread):
    def __init__(self) -> None:
        super().__init__(name = "world")
        self.ship_list = {}
        self.factory = None
        self.world_x, self.world_y = parse.Parse.get_world_size()
        self.hello_round = int(parse.Parse.get_holle_round())
        logging.info("世界格局已生成")

    def activate_ship_factory(self):
        """启动造船工厂"""
        self.factory = ship_factory.Factory(self.world_x, self.world_y)
        return self.factory

    def create_ship(self):
        """开始建造船只"""
        self.ship_list = self.factory.create_ship()
        return self.ship_list

    def run(self):
        self.begin()

    def begin(self):
        """开始仿真"""
        step_size = parse.Parse.get_sim_step()
        logging.info("开始仿真，当前仿真步长为：" + str(step_size) + "ms")
        # 开始按步长运行
        while not mns_time.Time.is_finish():
            time.sleep(0.000001)
            # 更新时间
            mns_time.Time.update_time()
            # 如果没到开始仿真时间则船只不开始运行
            if mns_time.Time.is_begin():
                self.all_ship_run(step_size)
            # 生成船只邻接表
            self.generate_adj_list(mns_time.Time.time)

    def all_ship_run(self, step_size):
        """开始运行所有船只"""
        for value in self.ship_list.values():
            if isinstance(value, ship.Ship):
                value.run_ship(step_size)

    def generate_adj_list(self, current_time: int):
        """每个hello间隙，生成船只邻接表"""
        ship_adj_list = {}
        # 根据当前时间决定是否更新邻接矩阵表
        if current_time % self.hello_round != 0:
            return
        # 获得所有船只名字list
        ship_all_list = list(self.ship_list.keys())
        ship_count = len(ship_all_list)
        for i in range(ship_count):
            ship1 = ship_all_list[i]
            for j in range(i + 1, ship_count):
                ship2 = ship_all_list[j]
                x1, y1 = self.ship_list[ship1].get_current_pos()
                x2, y2 = self.ship_list[ship2].get_current_pos()
                if self.is_connect(x1, y1, x2, y2):
                    self.add_edge(ship1, ship2, ship_adj_list)
        ship_adj_table.Table.write(ship_adj_list)

    def add_edge(self, u, v, ship_adj_list):
        if u not in ship_adj_list:
            ship_adj_list[u] = []
        if v not in ship_adj_list:
            ship_adj_list[v] = []
        ship_adj_list[u].append(v)
        ship_adj_list[v].append(u)

    def is_connect(self, x1, y1, x2, y2):
        dis = self.distance(x1, y1, x2, y2)
        max_dis = parse.Parse.get_communication_distance()
        if dis <= max_dis:
            return True
        return False

    def distance(self, x1, y1, x2, y2):
        """计算船只距离"""
        x = pow((x1 - x2), 2)
        y = pow((y1 - y2), 2)
        dis = math.sqrt(x + y)
        return dis
